package com.czk.writer;

import com.czk.utils.FileUtil;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;

import static org.objectweb.asm.Opcodes.*;

/**
 * @Author:ChenZhangKun
 * @Date: 2021/9/14 22:46
 */
public class GenerateCinit {
    public static void main(String[] args) {
        // 地址
        String path = "F:\\IdeaProjects\\asm\\target\\classes\\com\\czk\\sample\\GenerateCinit.class";
        // 生成的字节码字节流
        byte[] bytes = generateCinit();
        FileUtil.writeBytes(path, bytes);
    }

    private static byte[] generateCinit() {
        // 自动计算maxLocal
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        // 创建类
        cw.visit(V1_8, ACC_PUBLIC, "com/czk/sample/GenerateCinit", null, "java/lang/Object", null);
        {
            // 构造方法
            MethodVisitor methodVisitor = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            // 开始构造代码
            methodVisitor.visitCode();
            // 加载localVaraible第0号数据
            methodVisitor.visitVarInsn(ALOAD, 0);
            // 执行构造
            methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            // 返回
            methodVisitor.visitInsn(RETURN);
            // 计算max
            methodVisitor.visitMaxs(1, 1);
            // 结束
            methodVisitor.visitEnd();
        }
        {
            // 静态代码块
            MethodVisitor methodVisitor = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
            // 开始
            methodVisitor.visitCode();
            // 生成field
            methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            // 加载需要打印到operate stack中的值
            methodVisitor.visitLdcInsn("czk=========");
            // INVOKEVIRTUAL 方法指令
            // java/lang/PrintStream 方法拥有者
            // println方法名称
            // (Ljava/lang/String;)方法描述
            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            methodVisitor.visitInsn(RETURN);
            methodVisitor.visitMaxs(2, 0);
            methodVisitor.visitEnd();
        }
        cw.visitEnd();
        return cw.toByteArray();
    }
}
